package main.objects;

import main.FactageSmet;
import main.MainFrame;
import main.MsSQLConnect;

import javax.swing.tree.DefaultMutableTreeNode;
import java.math.BigDecimal;

import java.math.RoundingMode;
import java.sql.*;
import java.util.*;
import java.util.Date;

public class SmetNode extends DefaultMutableTreeNode {

    //region Поля для шапки списка смет
    private String headNum;
    private String headName;
    private String headStatus;
    private String headChange;
    private String headDateChange;
    private String headSum;
    private String headPz;

    //endregion

    //region Поля для шапки списка сметных строк
    private String headSmrNum;
    private String headSmrName;
    private String headSmrCode;
    private String headSmrUnit;
    private String headSmrVolume;
    private String headSmrT;
    private String headSmrMech;
    private String headSmrPz;
    //endregion

    private String smetBase;

    private int id, epsId, titulId, smetId, smrNum, change;

    private String name;
    private String status;
    private String comment;
    private String code;
    private String unit;
    private String type;

    private String num;
    private BigDecimal oz, em, zm, mt, pz, nr, sp, sum;
    private BigDecimal tzr, tzm;
    private BigDecimal fact;
    private BigDecimal volume;

    private ArrayList<SmetNode> smrs;
    private ArrayList<SmetResourceAssignment> smetRa;
    private Date dateChange;



    //--------------------------------------------------------------------------

    //region Флаги типа объекта
    private boolean isSmet = false;
    private boolean isChapter = false;
    private boolean isHeader = false;
    private boolean isSmr = false;
    private boolean isRoot = false;
    private boolean isHeadSmet = false;
    private boolean isHeadSmr = false;
    public boolean smetUnderExpanded = false;
    private boolean isLast = false;
    //endregion

    //region Поля для разделов
    private int chapterId, chapterNum, headerId;
    //endregion

    //region Конструктор для сметы
    public SmetNode(String name, String num, BigDecimal sum, String comment) {

        this.name = name;
        this.num = num;
        this.sum = sum;
        this.comment = comment;
        this.isSmet = true;
        this.status = "Актуальная";

    }
    //endregion

    //region Конструктор для раздела
    public SmetNode(String name, Integer chapterNum, int smetId) {

        this.name = name;
        this.chapterNum = chapterNum;
        this.smetId = smetId;
        this.isChapter = true;

    }
    //endregion

    //region Конструктор для заголовка
    public SmetNode(int smetId, String name, int chapterId) {

        this.name = name;
        this.chapterId = chapterId;
        this.smetId = smetId;
        this.isHeader = true;

    }
    //endregion

    public BigDecimal getOz() {
        return oz;
    }

    public BigDecimal getEm() {
        return em;
    }

    public BigDecimal getZm() {
        return zm;
    }

    public BigDecimal getNr() {
        return nr;
    }

    public BigDecimal getMt() {
        return mt;
    }

    public BigDecimal getSp() {
        return sp;
    }

    //region Конструктор для сметных строк
    public SmetNode(int smrNum, String code, String name, String unit, BigDecimal volume, BigDecimal tzr, BigDecimal oz, BigDecimal tzm, BigDecimal em, BigDecimal zm, BigDecimal mt, BigDecimal pz, BigDecimal nr, BigDecimal sp, BigDecimal sum, int headerId, int chapterId, int smetId) {

        this.smrNum = smrNum;
        this.name = name;
        this.code = code;
        this.unit = unit;
        this.volume = volume;

        this.headerId = headerId;
        this.chapterId = chapterId;
        this.smetId = smetId;

        this.isSmr = true;

        this.tzr = tzr;
        this.oz = oz;
        this.tzm = tzm;
        this.em = em;
        this.zm = zm;
        this.mt = mt;
        this.pz = pz;
        this.nr = nr;
        this.sp = sp;
        this.sum = sum;

        this.smetRa = new ArrayList<>();
    }
    //endregion

    public void createSmet() {

        java.sql.Date sqlDate = new java.sql.Date(Calendar.getInstance(TimeZone.getTimeZone("GMT+10")).getTime().getTime());
        dateChange = Calendar.getInstance(TimeZone.getTimeZone("GMT+10")).getTime();

        try {
            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("INSERT INTO Smet VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1, name);
            preparedStatement.setInt(2, MainFrame.SELECTED_EPS.getId());
            preparedStatement.setInt(3, MainFrame.SELECTED_EPS.getTitulId());
            preparedStatement.setString(4, num);
            preparedStatement.setBigDecimal(5, sum);
            preparedStatement.setString(6, "Актуальная");
            preparedStatement.setString(7, comment);
            preparedStatement.setBigDecimal(8, null);
            preparedStatement.setInt(9, 0);
            preparedStatement.setInt(10, 0);
            preparedStatement.setDate(11, sqlDate);
            preparedStatement.setInt(12, 0);
            preparedStatement.setString(13, smetBase);

            preparedStatement.executeUpdate();

            ResultSet rs = preparedStatement.getGeneratedKeys();

            if (rs.next()){
                id = rs.getInt(1);
                setUserObject(id + "-smet");
            }

            rs.close();
            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        if (MainFrame.ALL_EPS.containsKey(MainFrame.SELECTED_EPS.getId() + "-eps")) {
            if (MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().size() < 1) {
                MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().add(MainFrame.ALL_SMET.get("smethead"));
            }
            MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().add(this);
        }

        MainFrame.ALL_SMET.put(id + "-smet", this);
        MainFrame.treeSmet.ROOT_SMET_NODE.add(this);
        MainFrame.treeSmet.showSmet(MainFrame.SELECTED_EPS);
        MainFrame.treeSmet.treeModel.reload();

    }

    public void createChapter() {

        try {
            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("INSERT INTO Chapter VALUES (?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1, name);
            preparedStatement.setInt(2, chapterNum);
            preparedStatement.setInt(3, smetId);

            preparedStatement.executeUpdate();

            ResultSet rs = preparedStatement.getGeneratedKeys();

            if (rs.next()){
                id = rs.getInt(1);
                setUserObject(id + "-chapter");
            }

            rs.close();
            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        MainFrame.ALL_SMET.put(id + "-chapter", this);

    }

    public void createHeader() {

        try {
            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("INSERT INTO Header VALUES (?, ?, ?)", PreparedStatement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1, name);
            preparedStatement.setInt(2, chapterId);
            preparedStatement.setInt(3, smetId);

            preparedStatement.executeUpdate();

            ResultSet rs = preparedStatement.getGeneratedKeys();

            if (rs.next()){
                id = rs.getInt(1);
                setUserObject(id + "-header");
            }

            rs.close();
            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        MainFrame.ALL_SMET.put(id + "-header", this);
    }

    public void createSmr() {

        try {

            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");
            Statement stat = FactageSmet.IMPORT_FACTAGE_CONNECTION.createStatement();

            stat.executeUpdate(
                    "INSERT INTO Smr VALUES (" +
                    smrNum + ", '"
                    + code + "', '"
                    + name + "', '"
                    + unit + "', "
                    + volume + ", "
                    + headerId + ", "
                    + chapterId + ", "
                    + smetId + ", "
                    + tzr + ", "
                    + oz + ", "
                    + tzm + ", "
                    + em + ", "
                    + zm + ", "
                    + mt + ", "
                     + pz + ", "
                    + nr + ", "
                    + sp + ", "
                    + sum + ")  select @@identity as ident", Statement.RETURN_GENERATED_KEYS);
            ResultSet rs = stat.getGeneratedKeys();

            if (rs.next()){
                id = rs.getInt(1);
                setUserObject(id + "-smr");
            }

            rs.close();
            stat.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        MainFrame.ALL_SMET.put(id + "-smr", this);

    }

    public SmetNode(ResultSet rs, String type) throws SQLException {

        if (type.equals("smet")) {

            this.id = rs.getInt("id");
            this.name = rs.getString("name");
            this.epsId = rs.getInt("eps_id");
            this.titulId = rs.getInt("titul_id");
            this.num = rs.getString("num");
            this.isSmet = true;
            this.sum = new BigDecimal(rs.getDouble("sum")).setScale(6, RoundingMode.HALF_UP);
            this.status = rs.getString("status");
            this.comment = rs.getString("comment");
            this.fact = new BigDecimal(rs.getDouble("fact")).setScale(6, RoundingMode.HALF_UP);
            this.smrs = new ArrayList<>();
            this.dateChange = rs.getDate("date_change");
            this.isSmet = true;
            this.change = rs.getInt("change");
            this.pz = new BigDecimal(rs.getDouble("pz")).setScale(6, RoundingMode.HALF_UP);
            setUserObject(id + "-smet");

        } else if (type.equals("chapter")) {

            this.id = rs.getInt("id");
            this.name = rs.getString("name");
            this.chapterNum = rs.getInt("num");
            this.smetId = rs.getInt("smet_id");
            this.isChapter = true;
            setUserObject(id + "-chapter");

        } else if (type.equals("header")) {

            this.id = rs.getInt("id");
            this.name = rs.getString("name");
            this.chapterId = rs.getInt("chapter_id");
            this.smetId = rs.getInt("smet_id");
            this.isHeader = true;
            setUserObject(id + "-header");

        } else if (type.equals("smr")) {

            this.id = rs.getInt("id");
            this.smrNum = rs.getInt("num");
            this.code = rs.getString("code");
            this.name = rs.getString("name");

            this.unit = rs.getString("unit");
            this.volume = new BigDecimal(rs.getDouble("volume")).setScale(6, RoundingMode.HALF_UP);

            this.tzr = new BigDecimal(rs.getDouble("tzr")).setScale(6, RoundingMode.HALF_UP);
            this.oz = new BigDecimal(rs.getDouble("oz")).setScale(6, RoundingMode.HALF_UP);
            this.tzm = new BigDecimal(rs.getDouble("tzm")).setScale(6, RoundingMode.HALF_UP);
            this.em = new BigDecimal(rs.getDouble("em")).setScale(6, RoundingMode.HALF_UP);
            this.zm = new BigDecimal(rs.getDouble("zm")).setScale(6, RoundingMode.HALF_UP);
            this.mt = new BigDecimal(rs.getDouble("mt")).setScale(6, RoundingMode.HALF_UP);
            this.pz = new BigDecimal(rs.getDouble("pz")).setScale(6, RoundingMode.HALF_UP);
            this.nr = new BigDecimal(rs.getDouble("nr")).setScale(6, RoundingMode.HALF_UP);
            this.sp = new BigDecimal(rs.getDouble("sp")).setScale(6, RoundingMode.HALF_UP);
            this.sum = new BigDecimal(rs.getDouble("sum")).setScale(6, RoundingMode.HALF_UP);

            this.headerId = rs.getInt("header_id");
            this.chapterId = rs.getInt("chapter_id");
            this.smetId = rs.getInt("smet_id");

            this.isSmr = true;
            setUserObject(id + "-smr");

        }

    }


//-----------------------------------------------------------------------------------------------------

    public void copySmet() {

        SmetNode newSmet = new SmetNode(name, num, sum, comment);
        newSmet.setPz(pz);
        newSmet.createSmet();

        SmetNode parentSect = null;

        if (((SmetNode) this.getFirstChild()).isChapter) {

            for (SmetNode chapter : this.getChildren()) {

                SmetNode newChapter = new SmetNode(chapter.getName(), chapter.getChapterNum(), newSmet.getId());
                newSmet.add(newChapter);
                newChapter.createChapter();

                MainFrame.ALL_SMET.put(newChapter.getId() + "-chapter", newChapter);

                if (chapter.getChildren().isEmpty()) continue;

                if (((SmetNode) chapter.getFirstChild()).isHeader) {

                    for (SmetNode header : chapter.getChildren()) {

                        SmetNode newHeader = new SmetNode(newSmet.getId(), header.getName(), header.getChapterId());
                        newChapter.add(newHeader);
                        newHeader.createHeader();

                        MainFrame.ALL_SMET.put(newHeader.getId() + "-header", newHeader);

                        if (chapter.getChildren().isEmpty()) continue;

//                        for (SmetNode smr : header.getChildren()) {
//
//                            if (smr.isHeadSmr) continue;
//
//                            SmetNode newSmr = new SmetNode(
//                                    smr.getName(),
//                                    smr.getSmrNum(),
//                                    smr.getCode(),
//                                    smr.getUnit(),
//                                    smr.getVolume(),
//                                    newSmet.getId(),
//                                    newChapter.getId(),
//                                    newHeader.getId());
//
//                            newSmr.createSmr();
//
//                            if (newHeader.getChildren().isEmpty()) newHeader.add(new SmetNode("smrhead"));
//                            newHeader.add(newSmr);
//                            MainFrame.ALL_SMET.put(newSmr.getId() + "-smr", newSmr);

//                        }
                    }
                } else if (((SmetNode) chapter.getFirstChild()).isSmr) {

                }

            }

        } else {

            for (SmetNode smr : newSmet.getChildren()) {

                if (smr.isHeadSmr) continue;

//                SmetNode newSmr = new SmetNode(
//                        smr.getName(),
//                        smr.getSmrNum(),
//                        smr.getCode(),
//                        smr.getUnit(),
//                        smr.getVolume(),
//                        smr.getT(),
//                        smr.getMech(),
//                        smr.getMr(),
//                        newSmet.getId(),
//                        0);
//
//                newSmr.updateSmr();
//                newSmet.add(newSmr);
//
//                if (newSmet.getChildCount() == 0) {
//                    newSmet.add(new SmetNode("smrhead"));
//                }
//                newSmet.add(newSmr);
//
//                MainFrame.ALL_SMET.put(newSmr.getId() + "-smr", newSmr);

            }

        }

        MainFrame.treeSmet.showSmet(MainFrame.SELECTED_EPS);
        MainFrame.treeSmet.treeModel.reload();

    }

    public void updateSmetName() {

        try {

            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("UPDATE Smet set name = ?, num = ? where id = ?");
            preparedStatement.setString(1, name);
            preparedStatement.setString(2, num);
            preparedStatement.setInt(3, id);
            preparedStatement.executeUpdate();

            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        MainFrame.treeSmet.ROOT_SMET_NODE.add(this);
        MainFrame.treeSmet.showSmet(MainFrame.SELECTED_EPS);


    }

    public void updateSmetEPS() {

        try {

            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("UPDATE Smet set eps_id = ?, titul_id = ? where id = ?");
            preparedStatement.setInt(1, MainFrame.SELECTED_EPS.getId());
            preparedStatement.setInt(2, MainFrame.SELECTED_EPS.getTitulId());
            preparedStatement.setInt(3, id);
            preparedStatement.executeUpdate();

            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        if (MainFrame.ALL_EPS.containsKey(MainFrame.SELECTED_EPS.getId() + "-eps")) {
            if (MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().size() < 3) {
                MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().add(MainFrame.ALL_SMET.get("smethead"));
            }
            MainFrame.ALL_EPS.get(MainFrame.SELECTED_EPS.getId() + "-eps").getSmets().add(this);
        }

        MainFrame.treeSmet.ROOT_SMET_NODE.add(this);
        MainFrame.treeSmet.showSmet(MainFrame.SELECTED_EPS);

    }

    public void updateSmetPz() {

        try {

            FactageSmet.IMPORT_FACTAGE_CONNECTION = MsSQLConnect.ConnectDB("ImportFactage");

            PreparedStatement preparedStatement = FactageSmet.IMPORT_FACTAGE_CONNECTION.prepareStatement("UPDATE Smet set pz = ? where id = ?");
            preparedStatement.setDouble(1, pz.doubleValue());
            preparedStatement.setInt(2, id);
            preparedStatement.executeUpdate();

            preparedStatement.close();
            FactageSmet.IMPORT_FACTAGE_CONNECTION.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    //region Конструкторы для выгрузки из SQL

    public SmetNode(int id, String name) {

        this.id = id;
        this.name = name;
        this.isRoot = true;
        setUserObject(id + "__" + name);

    }

    //region Конструктор для шапок
    public SmetNode(String userObject) {

        if (userObject.equals("smethead")) {

            setUserObject("smethead");
            this.isHeadSmet = true;

        } else if (userObject.equals("smrhead")) {

            setUserObject("smrhead");
            this.isHeadSmr = true;

        }

    }
    //endregion

    //endregion


    //region Геттеры и сеттеры
    public boolean isHeadSmr() {
        return isHeadSmr;
    }

    public boolean isHeadSmet() {
        return isHeadSmet;
    }

    public boolean isSmet() {
        return isSmet;
    }

    public void setSmet(boolean isSmet) {
        this.isSmet = isSmet;
    }

    public boolean isSmr() {
        return isSmr;
    }

    public void setSmr(boolean isSmr) {
        this.isSmr = isSmr;
    }

    public boolean isRoot() {
        return isRoot;
    }

    public void setRoot(boolean isRoot) {
        this.isRoot = isRoot;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getEpsId() {
        return epsId;
    }

    public void setEpsId(int epsId) {
        this.epsId = epsId;
    }

    public int gettitulId() {
        return titulId;
    }

    public void setTitulId(int titulId) {
        this.titulId = titulId;
    }

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    public int getSmetId() {
        return smetId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public BigDecimal getSum() {
        return sum;
    }

    public void setSum(BigDecimal sum) {
        this.sum = sum;
    }

    public BigDecimal getFact() {
        return fact;
    }

    public List<SmetNode> getChildren() {return children; }

    public void setFact(BigDecimal fact) {
        this.fact = fact;
    }

    public BigDecimal getVolume() {
        return volume;
    }

    public void setVolume(BigDecimal volume) {
        this.volume = volume;
    }

    public BigDecimal getPz() {
        return pz;
    }

    public void setPz(BigDecimal pz) {
        this.pz = pz;
    }

    public int getSmrNum() {
        return smrNum;
    }

    public void setSmrNum(int smrNum) {
        this.smrNum = smrNum;
    }

    public ArrayList<SmetNode> getSmrs() {
        return smrs;
    }

    public int getChange() {
        return change;
    }

    public void setChange(int change) {
        this.change = change;
    }

    public Date getDateChange() {
        return dateChange;
    }

    public void setDateChange(Date dateChange) {
        this.dateChange = dateChange;
    }

    public boolean isLast() {
        return isLast;
    }

    public void setLast(boolean isLast) {
        this.isLast = isLast;
    }

    public String getSmetBase() {
        return smetBase;
    }

    public void setSmetBase(String smetBase) {
        this.smetBase = smetBase;
    }

    public boolean isChapter() {
        return isChapter;
    }

    public Integer getChapterNum() {
        return chapterNum;
    }

    public Integer getChapterId() {
        return chapterId;
    }

    public boolean isHeader() {
        return isHeader;
    }

    public int getHeaderId() {
        return headerId;
    }

    public void setHeaderId(int headerId) {
        this.headerId = headerId;
    }

    public BigDecimal getTzr() {
        return this.tzr;
    }

    public BigDecimal getTzm() {
        return this.tzm;
    }
    //endregion
}
